#pragma once

#include <iostream>
#include <memory>
#include <vector>
#include <string>
#include <stdexcept>
#include <array>

#include "njm_system.hpp"
#include "njm_ecs_frame_info.hpp"

#include "njm_model.hpp"
#include "njm_pipeline.hpp"
#include "njm_device.hpp"
#include "njm_camera.hpp"

namespace njm
{
    class EcsRenderSystem : public System
    {
    private:
    public:
        EcsRenderSystem();
        ~EcsRenderSystem();
        void Update(float deltaTime, Coordinator &coordinator) override;
    };

    class RenderSystem
    {
    public:
        struct ECSPushConstantData
        {
            glm::mat4 modelMat{1.0f};
            glm::mat4 normalMat{1.0f};
        };

        RenderSystem(NjmDevice &device,
                     VkRenderPass renderPass,
                     VkDescriptorSetLayout globalSetLayout,
                     std::string vertShaderPath, std::string fragShaderPath);
        ~RenderSystem();
        RenderSystem(const RenderSystem &) = delete;
        RenderSystem &operator=(const RenderSystem &) = delete;
        void render(ECSFrameInfo &frameInfo);

    private:
        NjmDevice &njmDevice;
        VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
        std::unique_ptr<NjmPipeline> njmPipeline = nullptr;

        std::string vertShaderPath{};
        std::string fragShaderPath{};

        void createPipelineLayout(VkDescriptorSetLayout globalSetLayout);
        void createPipeline(VkRenderPass renderPass);
    };

}